﻿using System;
using System.Collections.Generic;
using System.Windows;

namespace Red.Controls.Notification
{
    /// <summary>
    /// Manages notification popups for given window.
    /// </summary>
    public class NotificationDispatcher
    {
        /// <summary>
        /// Parent window of all notification popups created by this dispatcher.
        /// </summary>
        private Window _parentWindow;

        /// <summary>
        /// Margin between each notification, vertically.
        /// </summary>
        private const double _stackMargin = 20;

        /// <summary>
        /// Margin from right bottom corner of the parent window.
        /// </summary>
        private const double _parentWindowMargin = 40;

        /// <summary>
        /// List of currently active notifications.
        /// </summary>
        List<NotificationPopupWindow> _notifications = new List<NotificationPopupWindow>();

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="parentWindow">Parent window of all notification popups created by this dispatcher.</param>
        public NotificationDispatcher( Window parentWindow )
        {
            _parentWindow = parentWindow;
            _parentWindow.SizeChanged += Window_SizeChanged;
            _parentWindow.StateChanged += Window_StateChanged;
            _parentWindow.LocationChanged += Window_LocationChanged;
        }

        /// <summary>
        /// Create informational notification.
        /// </summary>
        /// <param name="text">Short text of the notification.</param>
        public void NotifyInformation( string text )
        {
            NotificationPopupWindow notification = CreateNotificationWindow();
            
            // TODO: assign icon to notification
            notification.Text = text;

            notification.StartNotification();
        }

        /// <summary>
        /// Create error notification.
        /// </summary>
        /// <param name="text">Short text of the notification.</param>
        public void NotifyError( string text )
        {
            NotificationPopupWindow notification = CreateNotificationWindow();

            // TODO: assign icon to notification
            notification.Text = text;

            notification.StartNotification();
        }

        /// <summary>
        /// Create warning notification.
        /// </summary>
        /// <param name="text">Short text of the notification.</param>
        public void NotifyWarning( string text )
        {
            NotificationPopupWindow notification = CreateNotificationWindow();

            // TODO: assign icon to notification
            notification.Text = text;

            notification.StartNotification();
        }

        /// <summary>
        /// Create notification window.
        /// </summary>
        /// <returns></returns>
        private NotificationPopupWindow CreateNotificationWindow()
        {
            NotificationPopupWindow notification = new NotificationPopupWindow( _parentWindow );
            _notifications.Add( notification );
            int index = _notifications.Count - 1;

            notification.Closed += ( object sender, EventArgs e ) =>
            {
                _notifications.Remove( notification );
                RepositionAllNotificationWindows();
            };

            LocateNotificationWindow( notification, index );

            return notification;
        }

        /// <summary>
        /// Place notification window in proper place relative to the parent window.
        /// </summary>
        /// <param name="window">Notification window.</param>
        /// <param name="stackIndex">Index on stack of notifications.</param>
        private void LocateNotificationWindow( NotificationPopupWindow window, int stackIndex )
        {
            double stackPosition = (window.Height + _stackMargin) * stackIndex;
            window.Left = _parentWindow.ActualWidth - window.Width - _parentWindowMargin;
            window.Top = _parentWindow.ActualHeight - window.Height - _parentWindowMargin - stackPosition;

            if( _parentWindow.WindowState != WindowState.Maximized )
            {
                window.Left += _parentWindow.Left;
                window.Top += _parentWindow.Top;
            }
        }

        /// <summary>
        /// Adjust positions of all currently active notification windows.
        /// </summary>
        private void RepositionAllNotificationWindows()
        {
            for ( int i = 0; i < _notifications.Count; ++i )
            {
                LocateNotificationWindow( _notifications[i], i );
            }
        }

        /// <summary>
        /// Reposition notifications when parent window size is changed.
        /// </summary>
        private void Window_SizeChanged( object sender, SizeChangedEventArgs e )
        {
            RepositionAllNotificationWindows();
        }

        /// <summary>
        /// Reposition notifications when parent window state is changed.
        /// </summary>
        private void Window_StateChanged( object sender, EventArgs e )
        {
            RepositionAllNotificationWindows();
        }

        /// <summary>
        /// Reposition notifications when parent window location is changed.
        /// </summary>
        private void Window_LocationChanged( object sender, EventArgs e )
        {
            RepositionAllNotificationWindows();
        }
    }
}
